#include <log4cpp/Category.hh>
#include <log4cpp/Appender.hh>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/Layout.hh>
#include <log4cpp/BasicLayout.hh>
#include <log4cpp/Priority.hh>
#include <FileAppender.hh>
using namespace log4cpp;

/**
 * Category     记录器
 * Priority     优先级(过滤器需要使用)
 * Layout       布局(格式化)
 * Appender     输出器(目的地)
 */
int main(int argc, char** argv) {
    /* 多态：父类指针指向子类实例对象 */

    /**
     * OstreamAppender
     * 参数一：目的地的名字，随便起
     * 参数二：需要otream*，传入&cout表示目的地是终端
     */
    Appender *appender1 = new  OstreamAppender("console",&std::cout);
    /**
     * 输出器指针调用setLayout，设定布局
     */
    appender1->setLayout(new  BasicLayout());

    /**
     * FileAppender
     * 参数一：目的地的名字，随便起
     * 参数二：输出日志的文件名
     */
    Appender *appender2 = new  FileAppender("default","program.log");
    appender2->setLayout(new  BasicLayout());

    /**
     * getRoot创建出根节点的Category对象，引用root进行绑定
     * 在代码中就可以用root指代根节点的Category对象
     */
    Category& root =  Category::getRoot();
    /**
     * 根节点设置优先级为WARN级别，代表系统级别
     * 如果日志信息的优先级高于或等于系统优先级，才会被处理
     * 如果日志信息的优先级低于系统的优先级，则直接过滤
     */
    root.setPriority( Priority::WARN);
    /**
     * 指定目的地，输出到终端
     */
    root.addAppender(appender1);

    /**
     * getInstance创建叶子节点的Category对象，会继承父节点的优先级和目的地
     * sub1变量是引用的名字
     * getInstance()的参数sub1是Category的名字，代表日志来源
     */
    Category& sub1 =  Category::getInstance(std::string("sub1"));
    sub1.addAppender(appender2);

    // use of functions for logging messages
    root.error("root error");   // 记录
    root.info("root info");     // pass
    sub1.error("sub1 error");   // 记录
    sub1.warn("sub1 warn");     // 记录

    // printf-style for logging variables
    root.warn("%d + %d == %s ?", 1, 1, "two");

    // use of streams for logging messages
    root << Priority::ERROR << "Streamed root error";
    root << Priority::INFO << "Streamed root info";
    sub1 << Priority::ERROR << "Streamed sub1 error";
    sub1 << Priority::WARN << "Streamed sub1 warn";

    // or this way:
    root.errorStream() << "Another streamed error";
    return 0;

}
